From 29b083850c38f1249e96bad60332c998f31c519c Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Wed, 7 Jul 2004 15:54:47 +0000 Subject: [PATCH] bitkeeper revision 1.1041.16.1 (40ec1cc7JZD3Tq_wg7Ea5ZjrczQ0_A) Starting to call xfrd from xend. --- .rootkeys | 2 + tools/Makefile | 3 + tools/libxutil/sys_net.c | 56 +- tools/python/xen/xend/XendDomain.py | 5 +- tools/python/xen/xend/XendMigrate.py | 94 +-- tools/xfrd/Make.xfrd | 2 +- tools/xfrd/connection.c | 32 + tools/xfrd/connection.h | 4 + tools/xfrd/sxpr_parser.c | 943 +++++++++++++++++++++++++++ tools/xfrd/sxpr_parser.h | 133 ++++ tools/xfrd/xen_domain.c | 4 +- tools/xfrd/xfrd.c | 118 ++-- tools/xfrd/xfrdClient.py | 10 +- 13 files changed, 1254 insertions(+), 152 deletions(-) create mode 100644 tools/xfrd/sxpr_parser.c create mode 100644 tools/xfrd/sxpr_parser.h diff --git a/.rootkeys b/.rootkeys index d8edf89b73..17a4abdc09 100644 --- a/.rootkeys +++ b/.rootkeys @@ -296,6 +296,8 @@ 40e9808e99OcM547cKMTfmCVSoWVAw tools/xfrd/select.h 40e9808e5_PLdodqVOSx0b4T_f5aeg tools/xfrd/sxpr.c 40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/xfrd/sxpr.h +40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/xfrd/sxpr_parser.c +40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/xfrd/sxpr_parser.h 40e9808eF3NVldqRNS5IHM8gbFAvpw tools/xfrd/xdr.c 40e9808ezXzoRHm7pybXU69NtnjimA tools/xfrd/xdr.h 40e9808edpUtf4bJ8IbqClPJj_OvbA tools/xfrd/xen_domain.c diff --git a/tools/Makefile b/tools/Makefile index b366034eb2..58934639bb 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -6,6 +6,7 @@ all: $(MAKE) -C examples $(MAKE) -C xentrace $(MAKE) -C python + $(MAKE) -C xfrd install: all $(MAKE) -C libxutil install @@ -14,6 +15,7 @@ install: all $(MAKE) -C examples install $(MAKE) -C xentrace install $(MAKE) -C python install + $(MAKE) -C xfrd install dist: $(TARGET) $(MAKE) prefix=`pwd`/../../install dist=yes install @@ -26,4 +28,5 @@ clean: $(MAKE) -C examples clean $(MAKE) -C xentrace clean $(MAKE) -C python clean + $(MAKE) -C xfrd clean diff --git a/tools/libxutil/sys_net.c b/tools/libxutil/sys_net.c index 0e7ac5d638..f38d919d9c 100644 --- a/tools/libxutil/sys_net.c +++ b/tools/libxutil/sys_net.c @@ -18,6 +18,12 @@ #include "sys_net.h" #include "sys_string.h" +#ifdef __KERNEL__ +# include +#else +# include +#endif + /** @file * All network data are kept in network order and only converted to * host order for display. Network data includes IP addresses, port numbers and @@ -80,7 +86,7 @@ inline static int indexof(const char *s, int n, char c){ * * @param s input string * @param address where to put the address - * @return 0 on success, -1 on error + * @return 0 on success, negative on error */ int get_inet_addr(const char *s, unsigned long *address){ // Number of bits in a byte. @@ -96,7 +102,7 @@ int get_inet_addr(const char *s, unsigned long *address){ unsigned long addr = 0; unsigned long v; int i; - int err = -1; + int err = -EINVAL; // Bit shift for the current byte. int shift = BYTE_BITS * (WORD_BYTES - 1); char buf[64]; @@ -168,18 +174,18 @@ int inet_aton(const char *address, struct in_addr *inp){ * * @param name input hostname or address string * @param address where to put the address - * @return 1 if address found OK, 0 otherwise + * @return 0 if address found OK, nonzero otherwise */ int get_host_address(const char *name, unsigned long *address){ #ifdef __KERNEL__ - return get_inet_addr(name, address) == 0; + return get_inet_addr(name, address); #else struct hostent *host = gethostbyname(name); if(!host){ - return 0; + return -EINVAL; } *address = ((struct in_addr *)(host->h_addr))->s_addr; - return 1; + return 0; #endif } @@ -187,33 +193,33 @@ int get_host_address(const char *name, unsigned long *address){ * * @param name service name * @param port where to put the port - * @return 1 if service port found OK, 0 otherwise + * @return 0 if service port found OK, negative otherwise */ int get_service_port(const char *name, unsigned long *port){ #ifdef __KERNEL__ - return 0; + return -ENOSYS; #else struct servent *service; service = getservbyname(name, 0); if(!service){ - return 0; + return -EINVAL; } *port = service->s_port; - return 1; + return 0; #endif } /** Convert a port number (in network order) to a service name. * * @param port the port number - * @return service name if found OK, 0 otherwise + * @return service name if found OK, NULL otherwise */ char *get_port_service(unsigned long port){ #ifdef __KERNEL__ - return 0; + return NULL; #else struct servent *service = getservbyport(port, 0); - return (service ? service->s_name : 0); + return (service ? service->s_name : NULL); #endif } @@ -221,19 +227,27 @@ char *get_port_service(unsigned long port){ * * @param s input to convert * @param port where to put the port - * @return 1 if port found OK, 0 otherwise + * @return 0 if port found OK, -1 otherwise */ int convert_service_to_port(const char *s, unsigned long *port){ - int ok = 0; + int err = 0; unsigned long value; - if(convert_atoul(s, &value)){ - ok = get_service_port(s, &value); + printf("%s> %s\n", __FUNCTION__, s); + if(convert_atoul(s, &value) == 0){ + int ok = (0 <= value) && (value <= PORT_MAX); + printf("> value = %ld\n", value); + if(ok){ + value = htons((unsigned short)value); + } else { + err = -EINVAL; + } } else { - ok = (0 <= value) && (value <= PORT_MAX); - value = htons((unsigned short)value); + printf("> get_service_port...\n"); + err = get_service_port(s, &value); } - *port = (ok ? value : 0); - return ok; + *port = (err ? 0: value); + printf("%s< err=%d\n", __FUNCTION__, err); + return err; } #define MAC_ELEMENT_N 6 // Number of elements in a MAC address. diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 8b9db8101c..d52c93dda6 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -19,6 +19,7 @@ xroot = XendRoot.instance() import XendDB import XendDomainInfo import XendConsole +import XendMigrate import EventServer from xen.xend.server import SrvDaemon @@ -423,7 +424,9 @@ class XendDomain: """ # Need a cancel too? # Don't forget to cancel restart for it. - pass + dom = int(id) + xmigrate = XendMigrate.instance() + return xmigrate.migrate_begin(dom, dst) def domain_save(self, id, dst, progress=0): """Save domain state to file, destroy domain on success. diff --git a/tools/python/xen/xend/XendMigrate.py b/tools/python/xen/xend/XendMigrate.py index a598913792..a4a4183ceb 100644 --- a/tools/python/xen/xend/XendMigrate.py +++ b/tools/python/xen/xend/XendMigrate.py @@ -14,11 +14,6 @@ import sxp import XendDB import EventServer; eserver = EventServer.instance() -from xen.xend.packing import SxpPacker, SxpUnpacker -from xen.xend import XendDomain -xd = XendDomain.instance() - - XFRD_PORT = 8002 XFR_PROTO_MAJOR = 1 @@ -27,55 +22,63 @@ XFR_PROTO_MINOR = 0 class Migrate(Protocol): def __init__(self, minfo): - self.packer = None - self.unpacker = None + self.parser = sxp.Parser() self.minfo = minfo def connectionMade(self): - self.packer = SxpPacker(self.transport) - self.unpacker = SxpPacker() # Send hello. - self.packer.pack(['xfr.hello', XFR_PROTO_MAJOR, XFR_PROTO_MINOR]) + self.request(['xfr.hello', XFR_PROTO_MAJOR, XFR_PROTO_MINOR]) # Send migrate. vmconfig = self.minfo.vmconfig() if not vmconfig: self.loseConnection() return - self.packer.pack(['xfr.migrate', - self.minfo.src_dom, - vmconfig, - self.minfo.dst_host, - self.minfo.dst_port]) + self.request(['xfr.migrate', + self.minfo.src_dom, + vmconfig, + self.minfo.dst_host, + self.minfo.dst_port]) + + def request(self, req): + sxp.show(req, out=self.transport) + self.transport.write(' \n') + + def loseConnection(self): + self.transport.loseConnection() def connectionLost(self, reason): self.minfo.closed(reason) - def dataReceived(self, data): - try: - self.unpacker.reset(data) - val = self.unpacker.unpack() - print 'dataReceived>', 'val=', val - op = val[0] - op.replace('.', '_') - if op.startwith('xfr_'): - fn = getattr(self, op, self.unknown) - else: - fn = self.unknown - fn(val) - except Exception, ex: - print 'dataReceived>', ex - pass + def dispatch(self, val): + op = sxp.name(val) + op = op.replace('.', '_') + if op.startswith('xfr_'): + fn = getattr(self, op, self.unknown) + else: + fn = self.unknown() + fn(val) + def dataReceived(self, data): + self.parser.input(data) + if self.parser.ready(): + val = self.parser.get_val() + self.dispatch(val) + if self.parser.at_eof(): + self.loseConnection() + def unknown(self, val): print 'unknown>', val def xfr_progress(self, val): print 'xfr_progress>', val - def xfr_error(self, val): + def xfr_err(self, val): # If we get an error with non-zero code the migrate failed. # An error with code zero indicates hello success. - err = int(val[1]) + print 'xfr_err>', val + v = sxp.child(val) + print 'xfr_err>', type(v), v + err = int(sxp.child(val)) if not err: return self.minfo.error(err); self.loseConnection() @@ -83,14 +86,15 @@ class Migrate(Protocol): def xfr_ok(self, val): # An ok indicates migrate completed successfully, and contains # the new domain id on the remote system. - dom = int(val[1]) + print 'xfr_ok>', val + dom = int(sxp.child(val)) self.minfo.ok(dom) self.loseConnection() class MigrateClientFactory(ClientFactory): def __init__(self, minfo): - ClientFactory.__init__(self) + #ClientFactory.__init__(self) self.minfo = minfo def startedConnecting(self, connector): @@ -116,7 +120,7 @@ class XendMigrateInfo: self.state = 'begin' self.src_host = socket.gethostname() self.src_dom = dom - self.dst_host = dst + self.dst_host = host self.dst_port = port self.dst_dom = None self.start = 0 @@ -139,12 +143,18 @@ class XendMigrateInfo: return sxpr def vmconfig(self): - dominfo = xd.domain_get(self.dom) + print 'vmconfig>' + from xen.xend import XendDomain + xd = XendDomain.instance() + + dominfo = xd.domain_get(self.src_dom) + print 'vmconfig>', type(dominfo), dominfo if dominfo: - val = return sxp.to_string(dominfo) + val = sxp.to_string(dominfo.sxpr()) else: val = None - return None + print 'vmconfig<', 'val=', type(val), val + return val def error(self, err): self.state = 'error' @@ -153,7 +163,7 @@ class XendMigrateInfo: self.state = 'ok' self.dst_dom = dom - def close(self): + def closed(self, reason=None): if self.state =='ok': eserver.inject('xend.migrate.ok', self.sxpr()) else: @@ -208,15 +218,15 @@ class XendMigrate: def migrate_get(self, id): return self.migrate.get(id) - def migrate_begin(self, dom, host): + def migrate_begin(self, dom, host, port=XFRD_PORT): # Check dom for existence, not migrating already. # Subscribe to migrate notifications (for updating). id = self.nextid() - info = XenMigrateInfo(id, dom, host, XFRD_PORT) + info = XendMigrateInfo(id, dom, host, port) self._add_migrate(id, info) mcf = MigrateClientFactory(info) reactor.connectTCP('localhost', XFRD_PORT, mcf) - return info.deferred + return info def instance(): global inst diff --git a/tools/xfrd/Make.xfrd b/tools/xfrd/Make.xfrd index 39f3afd3c5..bb746d6bef 100644 --- a/tools/xfrd/Make.xfrd +++ b/tools/xfrd/Make.xfrd @@ -15,7 +15,7 @@ UTIL_LIB_SRC += lzi_stream.c UTIL_LIB_SRC += marshal.c UTIL_LIB_SRC += string_stream.c UTIL_LIB_SRC += sxpr.c -#UTIL_LIB_SRC += sxpr_parser.c +UTIL_LIB_SRC += sxpr_parser.c UTIL_LIB_SRC += sys_net.c UTIL_LIB_SRC += sys_string.c #UTIL_LIB_SRC += util.c diff --git a/tools/xfrd/connection.c b/tools/xfrd/connection.c index 26dca9968b..36f2ca8475 100644 --- a/tools/xfrd/connection.c +++ b/tools/xfrd/connection.c @@ -8,6 +8,7 @@ #include "connection.h" #include "file_stream.h" #include "lzi_stream.h" +#include "sxpr_parser.h" #define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args) #define wprintf(fmt, args...) fprintf(stderr, "[WARN] %s" fmt, __FUNCTION__, ##args) @@ -161,3 +162,34 @@ void Conn_close(Conn *conn){ if(conn->out) IOStream_close(conn->out); shutdown(conn->sock, 2); } + +int Conn_sxpr(Conn *conn, Sxpr *sxpr){ + int err = 0; + Sxpr val = ONONE; + int c = 0; + + dprintf(">\n"); + if(!conn->parser){ + conn->parser = Parser_new(); + set_error_stream(conn->parser, iostdout); + } + while(!err && c >= 0 && !Parser_ready(conn->parser)){ + c = IOStream_getc(conn->in); + printf("%c", (char)c); + if(c < 0){ + err = Parser_input_eof(conn->parser); + } else { + err = Parser_input_char(conn->parser, c); + } + } + if(Parser_ready(conn->parser)){ + val = Parser_get_val(conn->parser); + } + if(err){ + objfree(val); + val = ONONE; + } + *sxpr = val; + dprintf("< err=%d\n", err); + return err; +} diff --git a/tools/xfrd/connection.h b/tools/xfrd/connection.h index 790c01f1e8..2b67e767ba 100644 --- a/tools/xfrd/connection.h +++ b/tools/xfrd/connection.h @@ -5,6 +5,7 @@ #include #include "iostream.h" +#include "sxpr_parser.h" /** A connection. * The underlying transport is a socket. @@ -15,6 +16,7 @@ typedef struct Conn { int sock; IOStream *in; IOStream *out; + Parser *parser; } Conn; enum { @@ -29,4 +31,6 @@ extern int Conn_init(Conn *conn, int flags, int sock, struct sockaddr_in addr); extern int Conn_connect(Conn *conn, int flags, struct in_addr ipaddr, uint16_t port); extern void Conn_close(Conn *conn); +extern int Conn_sxpr(Conn *conn, Sxpr *sxpr); + #endif /* ! _VFC_CONNECTION_H_ */ diff --git a/tools/xfrd/sxpr_parser.c b/tools/xfrd/sxpr_parser.c new file mode 100644 index 0000000000..dbe386a862 --- /dev/null +++ b/tools/xfrd/sxpr_parser.c @@ -0,0 +1,943 @@ + +#ifdef __KERNEL__ +# include +# include +# include +# include +# include +#else +# include +# include +#endif + +#include "iostream.h" +#include "lexis.h" +#include "sxpr_parser.h" +#include "sys_string.h" +#include "enum.h" + +/** @file + * Sxpr parsing. + * + * So that the parser does not leak memory, all sxprs constructed by + * the parser must be freed on error. On successful parse the sxpr + * returned becomes the responsibility of the caller. + * + * @author Mike Wray + */ + +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args) +#define printf(fmt, args...) IOStream_print(iostdout, fmt, ##args) + +static void reset(Parser *z); +static int inputchar(Parser *p, char c); +static int savechar(Parser *p, char c); +extern void parse_error(Parser *in); +extern void parse_error_id(Parser *in, ParseErrorId id); + +static int begin_start(Parser *p, char c); +static int state_start(Parser *p, char c); +static int end_start(Parser *p); + +static int begin_comment(Parser *p, char c); +static int state_comment(Parser *p, char c); +static int end_comment(Parser *p); + +static int begin_string(Parser *p, char c); +static int state_string(Parser *p, char c); +static int end_string(Parser *p); +static int state_escape(Parser *p, char c); +static int state_octal(Parser *p, char c); +static int state_hex(Parser *p, char c); + +static int begin_atom(Parser *p, char c); +static int state_atom(Parser *p, char c); +static int end_atom(Parser *p); + +static int state_list(Parser *p, char c); +static int begin_list(Parser *p, char c); +static int end_list(Parser *p); + +/** Print a parse error. + * + * @param in parser + * @param msg format followed by printf arguments + */ +void eprintf(Parser *in, char *msg, ...){ + va_list args; + if(in->error_out){ + va_start(args, msg); + IOStream_vprint(in->error_out, msg, args); + va_end(args); + } +} + +/** Print a parse warning. + * + * @param in parser + * @param msg format followed by printf arguments + */ +void wprintf(Parser *in, char *msg, ...){ + va_list args; + if(in->error_out){ + va_start(args, msg); + IOStream_vprint(in->error_out, msg, args); + va_end(args); + } +} + +/*============================================================================*/ + +/** Record defining the message for a parse error. */ +typedef struct { + ParseErrorId id; + char *message; +} ParseError; + +/** Format for printing parse error messages. */ +#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s" + +/** Message catalog for the parse error codes. */ +static ParseError catalog[] = { + { PARSE_ERR_UNSPECIFIED, "unspecified error" }, + { PARSE_ERR_NOMEM, "out of memory" }, + { PARSE_ERR_UNEXPECTED_EOF, "unexpected end of input" }, + { PARSE_ERR_TOKEN_TOO_LONG, "token too long" }, + { PARSE_ERR_INVALID_SYNTAX, "syntax error" }, + { PARSE_ERR_INVALID_ESCAPE, "invalid escape" }, + { 0, NULL } +}; + +/** Number of entries in the message catalog. */ +const static int catalog_n = sizeof(catalog)/sizeof(ParseError); + +void ParserState_free(ParserState *z){ + if(!z) return; + objfree(z->val); + deallocate(z); +} + +int ParserState_new(ParserStateFn *fn, char *name, + ParserState *parent, ParserState **val){ + int err = 0; + ParserState *z; + z = ALLOCATE(ParserState); + if(z){ + z->name = name; + z->fn = fn; + z->parent = parent; + z->val = ONULL; + } else { + err = -ENOMEM; + } + if(!err) *val = z; + return err; +} + +/** Free a parser. + * No-op if the parser is null. + * + * @param z parser + */ +void Parser_free(Parser *z){ + if(!z) return; + objfree(z->val); + z->val = ONONE; + deallocate(z); +} + +/** Create a new parser. The error stream defaults to null. + */ +Parser * Parser_new(void){ + Parser *z = ALLOCATE(Parser); + int err = -ENOMEM; + + if(!z) goto exit; + err = 0; + reset(z); + exit: + if(err){ + Parser_free(z); + z = NULL; + } + return z; +} + +/** Get the next character. + * Records the character read in the parser, + * and sets the line and character counts. + * + * @param p parser + * @return error flag: 0 on success, non-zero on error + */ +static int inputchar(Parser *p, char c){ + int err = 0; + if(c=='\n'){ + p->line_no++; + p->char_no = 0; + } else { + p->char_no++; + } + return err; +} + +static int savechar(Parser *p, char c){ + int err = 0; + if(p->buf_i >= p->buf_n){ + err = -ENOMEM; + goto exit; + } + p->buf[p->buf_i] = c; + p->buf_i++; + exit: + return err; +} + +int Parser_input_char(Parser *p, char c){ + int err = 0; + if(at_eof(p)){ + //skip; + } else { + inputchar(p, c); + } + if(!p->state){ + err = begin_start(p, c); + if(err) goto exit; + } + err = p->state->fn(p, c); + exit: + return err; +} + +int Parser_input_eof(Parser *p){ + int err = 0; + p->eof = 1; + err = Parser_input_char(p, IOSTREAM_EOF); + return err; +} + +int Parser_input(Parser *p, char *buf, int buf_n){ + int err = 0; + int i = 0; + if(buf_n <= 0){ + err = Parser_input_eof(p); + goto exit; + } + for(i = 0; istate, &p->state); + return err; +} + +int Parser_pop(Parser *p){ + int err = 0; + ParserState *s = p->state; + p->state = s->parent; + ParserState_free(s); + return err; +} + +int Parser_return(Parser *p){ + int err = 0; + Sxpr val = ONONE; + if(!p->state){ + err = -EINVAL; + goto exit; + } + val = p->state->val; + p->state->val = ONONE; + err = Parser_pop(p); + if(err) goto exit; + if(p->state){ + err = cons_push(&p->state->val, val); + } else { + val = nrev(val); + p->val = val; + } + exit: + if(err){ + objfree(val); + } + return err; +} + +/** Determine if a character is a separator. + * + * @param p parser + * @param c character to test + * @return 1 if a separator, 0 otherwise + */ +static int is_separator(Parser *p, char c){ + return in_sep_class(c); +} + +/** Return the current token. + * The return value points at the internal buffer, so + * it must not be modified (or freed). Use copy_token() if you need a copy. + * + * @param p parser + * @return token + */ +char *peek_token(Parser *p){ + return p->buf; +} + +/** Return a copy of the current token. + * The returned value should be freed when finished with. + * + * @param p parser + * @return copy of token + */ +char *copy_token(Parser *p){ + return strdup(peek_token(p)); +} + +static int do_intern(Parser *p){ + int err = 0; + Sxpr obj = intern(peek_token(p)); + if(NOMEMP(obj)){ + err = -ENOMEM; + } else { + p->state->val = obj; + } + return err; +} + +static int do_string(Parser *p){ + int err = 0; + Sxpr obj; + obj = string_new(peek_token(p)); + if(NOMEMP(obj)){ + err = -ENOMEM; + } else { + p->state->val = obj; + } + return err; +} + +void newtoken(Parser *p){ + memset(p->buf, 0, p->buf_n); + p->buf_i = 0; + p->tok_begin_line = p->line_no; + p->tok_begin_char = p->char_no; +} + +int get_escape(char c, char *d){ + int err = 0; + switch(c){ + case 'a': *d = '\a'; break; + case 'b': *d = '\b'; break; + case 'f': *d = '\f'; break; + case 'n': *d = '\n'; break; + case 'r': *d = '\r'; break; + case 't': *d = '\t'; break; + case 'v': *d = '\v'; break; + case c_escape: *d = c_escape; break; + case c_single_quote: *d = c_single_quote; break; + case c_double_quote: *d = c_double_quote; break; + default: + err = -EINVAL; + } + return err; +} + +int Parser_ready(Parser *p){ + return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val)); +} + +Sxpr Parser_get_val(Parser *p){ + Sxpr v = ONONE; + if(CONSP(p->val)){ + v = CAR(p->val); + p->val = CDR(p->val); + } else if (CONSP(p->start_state->val)){ + p->val = p->start_state->val; + p->val = nrev(p->val); + p->start_state->val = ONULL; + v = CAR(p->val); + p->val = CDR(p->val); + } + return v; +} + +Sxpr Parser_get_all(Parser *p){ + Sxpr v = ONULL; + if(CONSP(p->val)){ + v = p->val; + p->val = ONONE; + } else if(CONSP(p->start_state->val)){ + v = p->start_state->val; + p->start_state->val = ONULL; + v = nrev(v); + } + return v; +} + +int begin_start(Parser *p, char c){ + int err = 0; + err = Parser_push(p, state_start, "start"); + if(err) goto exit; + p->start_state = p->state; + exit: + return err; +} + +int state_start(Parser *p, char c){ + int err = 0; + if(at_eof(p)){ + err = end_start(p); + } else if(in_space_class(c)){ + //skip + } else if(in_comment_class(c)){ + begin_comment(p, c); + } else if(c == c_list_open){ + begin_list(p, c); + } else if(c == c_list_close){ + parse_error(p); + err = -EINVAL; + } else if(in_string_quote_class(c)){ + begin_string(p, c); + } else if(in_printable_class(c)){ + begin_atom(p, c); + } else if(c == 0x04){ + //ctrl-D, EOT: end-of-text. + Parser_input_eof(p); + } else { + parse_error(p); + err = -EINVAL; + } + return err; +} + +int end_start(Parser *p){ + int err = 0; + err = Parser_return(p); + return err; +} + +int begin_comment(Parser *p, char c){ + int err = 0; + err = Parser_push(p, state_comment, "comment"); + if(err) goto exit; + err = inputchar(p, c); + exit: + return err; +} + +int state_comment(Parser *p, char c){ + int err = 0; + if(c == '\n' || at_eof(p)){ + err = end_comment(p); + } else { + err = inputchar(p, c); + } + return err; +} + +int end_comment(Parser *p){ + return Parser_pop(p); +} + +int begin_string(Parser *p, char c){ + int err = 0; + err = Parser_push(p, state_string, "string"); + if(err) goto exit; + newtoken(p); + p->state->delim = c; + exit: + return err; +} + +int state_string(Parser *p, char c){ + int err = 0; + if(at_eof(p)){ + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); + err = -EINVAL; + } else if(c == p->state->delim){ + err = end_string(p); + } else if(c == '\\'){ + err = Parser_push(p, state_escape, "escape"); + } else { + err = savechar(p, c); + } + return err; +} + +int end_string(Parser *p){ + int err = 0; + err = do_string(p); + if(err) goto exit; + err = Parser_return(p); + exit: + return err; +} + +int state_escape(Parser *p, char c){ + int err = 0; + char d; + if(at_eof(p)){ + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); + err = -EINVAL; + goto exit; + } + if(get_escape(c, &d) == 0){ + err = savechar(p, d); + if(err) goto exit; + err = Parser_pop(p); + } else if(c == 'x'){ + p->state->fn = state_hex; + p->state->ival = 0; + p->state->count = 0; + } else { + p->state->fn = state_octal; + p->state->ival = 0; + p->state->count = 0; + err = Parser_input_char(p, c); + } + exit: + return err; +} + +int octaldone(Parser *p){ + int err = 0; + char d = (char)(p->state->ival & 0xff); + err = Parser_pop(p); + if(err) goto exit; + err = Parser_input_char(p, d); + exit: + return err; +} + +int octaldigit(Parser *p, char c){ + int err = 0; + p->state->ival *= 8; + p->state->ival += c - '0'; + p->state->count++; + if(err) goto exit; + if(p->state->ival < 0 || p->state->ival > 0xff){ + parse_error(p); + err = -EINVAL; + goto exit; + } + if(p->state->count == 3){ + err = octaldone(p); + } + exit: + return err; +} + +int state_octal(Parser *p, char c){ + int err = 0; + if(at_eof(p)){ + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); + err = -EINVAL; + goto exit; + } else if('0' <= c && c <= '7'){ + err = octaldigit(p, c); + } else { + err = octaldone(p); + if(err) goto exit; + Parser_input_char(p, c); + } + exit: + return err; +} + +int hexdone(Parser *p){ + int err = 0; + char d = (char)(p->state->ival & 0xff); + err = Parser_pop(p); + if(err) goto exit; + err = Parser_input_char(p, d); + exit: + return err; +} + +int hexdigit(Parser *p, char c, char d){ + int err = 0; + p->state->ival *= 16; + p->state->ival += c - d; + p->state->count++; + if(err) goto exit; + if(p->state->ival < 0 || p->state->ival > 0xff){ + parse_error(p); + err = -EINVAL; + goto exit; + } + if(p->state->count == 2){ + err = hexdone(p); + } + exit: + return err; +} + +int state_hex(Parser *p, char c){ + int err = 0; + if(at_eof(p)){ + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); + err = -EINVAL; + goto exit; + } else if('0' <= c && c <= '9'){ + err = hexdigit(p, c, '0'); + } else if('A' <= c && c <= 'F'){ + err = hexdigit(p, c, 'A'); + } else if('a' <= c && c <= 'f'){ + err = hexdigit(p, c, 'a'); + } else if(p->state->count){ + err =hexdone(p); + if(err) goto exit; + Parser_input_char(p, c); + } + exit: + return err; +} + +int begin_atom(Parser *p, char c){ + int err = 0; + err = Parser_push(p, state_atom, "atom"); + if(err) goto exit; + newtoken(p); + err = savechar(p, c); + exit: + return err; +} + +int state_atom(Parser *p, char c){ + int err = 0; + if(at_eof(p)){ + err = end_atom(p); + } else if(is_separator(p, c) || + in_space_class(c) || + in_comment_class(c)){ + err = end_atom(p); + if(err) goto exit; + err = Parser_input_char(p, c); + } else { + err = savechar(p, c); + } + exit: + return err; +} + +int end_atom(Parser *p){ + int err = 0; + err = do_intern(p); + if(err) goto exit; + err = Parser_return(p); + exit: + return err; +} + +int state_list(Parser *p, char c){ + int err = 0; + if(at_eof(p)){ + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); + err = -EINVAL; + } else if(c == c_list_close){ + p->state->val = nrev(p->state->val); + err = end_list(p); + } else { + err = state_start(p, c); + } + return err; + +} + +int begin_list(Parser *p, char c){ + return Parser_push(p, state_list, "list"); +} + +int end_list(Parser *p){ + return Parser_return(p); +} + +/** Reset the fields of a parser to initial values. + * + * @param z parser + */ +static void reset(Parser *z){ + IOStream *error_out = z->error_out; + int flags = z->flags; + memzero(z, sizeof(Parser)); + z->buf_n = sizeof(z->buf) - 1; + z->buf_i = 0; + z->line_no = 1; + z->char_no = 0; + z->error_out = error_out; + z->flags = flags; +} + +/** Set the parser error stream. + * Parse errors are reported on the the error stream if it is non-null. + * + * @param z parser + * @param error_out error stream + */ +void set_error_stream(Parser *z, IOStream *error_out){ + if(z){ + z->error_out = error_out; + } +} + +/** Get the parser error message for an error code. + * + * @param id error code + * @return error message (empty string if the code is unknown) + */ +static char *get_message(ParseErrorId id){ + int i; + for(i=0; iline_no; +} + +/** Get the column number. + * + * @param in parser + */ +int get_column(Parser *in){ + return in->char_no; +} + +/** Get the line number the current token started on. + * + * @param in parser + */ +int get_tok_line(Parser *in){ + return in->tok_begin_line; +} + +/** Get the column number the current token started on. + * + * @param in parser + */ +int get_tok_column(Parser *in){ + return in->tok_begin_char; +} + +/** Report a parse error. + * Does nothing if the error stream is null or there is no error. + * + * @param in parser + */ +static void report_error(Parser *in){ + if(in->error_out && in->err){ + char *msg = get_message(in->err); + char *tok = peek_token(in); + IOStream_print(in->error_out, PARSE_ERR_FMT, + get_tok_line(in), get_tok_column(in), msg); + if(tok && tok[0]){ + IOStream_print(in->error_out, " '%s'", tok); + } + IOStream_print(in->error_out, "\n"); + } +} + +/** Get the error message for the current parse error code. + * Does nothing if there is no error. + * + * @param in parser + * @param buf where to place the message + * @param n maximum number of characters to place in buf + * @return current error code (zero for no error) + */ +int parse_error_message(Parser *in, char *buf, int n){ + if(in->err){ + char *msg = get_message(in->err); + snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg); + } + return in->err; +} + +/** Flag an unspecified parse error. All subsequent reads will fail. + * + * @param in parser + */ +void parse_error(Parser *in){ + parse_error_id(in, PARSE_ERR_INVALID_SYNTAX); +} + +/** Flag a parse error. All subsequent reads will fail. + * Does not change the parser error code if it is already set. + * + * @param in parser + * @param id error code + */ +void parse_error_id(Parser *in, ParseErrorId id){ + if(!in->err){ + in->err = id; + report_error(in); + } +} + +/** Test if the parser's error flag is set. + * + * @param in parser + * @return 1 if set, 0 otherwise + */ +int has_error(Parser *in){ + return (in->err > 0); +} + +/** Test if the parser is at end of input. + * + * @param in parser + * @return 1 if at EOF, 0 otherwise + */ +int at_eof(Parser *p){ + return p->eof; +} + +//#define SXPR_PARSER_MAIN +#ifdef SXPR_PARSER_MAIN +/* Stuff for standalone testing. */ + +#include "file_stream.h" +#include "string_stream.h" + +int stringof(Sxpr exp, char **s){ + int err = 0; + if(ATOMP(exp)){ + *s = atom_name(exp); + } else if(STRINGP(exp)){ + *s = string_string(exp); + } else { + err = -EINVAL; + *s = NULL; + } + return err; +} + +int child_string(Sxpr exp, Sxpr key, char **s){ + int err = 0; + Sxpr val = sxpr_child_value(exp, key, ONONE); + err = stringof(val, s); + return err; +} + +int intof(Sxpr exp, int *v){ + int err = 0; + char *s; + unsigned long l; + if(INTP(exp)){ + *v = OBJ_INT(exp); + } else { + err = stringof(exp, &s); + if(err) goto exit; + err = convert_atoul(s, &l); + *v = (int)l; + } + exit: + return err; +} + +int child_int(Sxpr exp, Sxpr key, int *v){ + int err = 0; + Sxpr val = sxpr_child_value(exp, key, ONONE); + err = intof(val, v); + return err; +} + +int eval_vnet(Sxpr exp){ + int err = 0; + Sxpr oid = intern("id"); + int id; + err = child_int(exp, oid, &id); + if(err) goto exit; + dprintf("> vnet id=%d\n", id); + exit: + dprintf("< err=%d\n", err); + return err; +} + +int eval_connect(Sxpr exp){ + int err = 0; + Sxpr ovif = intern("vif"); + Sxpr ovnet = intern("vnet"); + char *vif; + int vnet; + + err = child_string(exp, ovif, &vif); + if(err) goto exit; + err = child_int(exp, ovnet, &vnet); + if(err) goto exit; + dprintf("> connect vif=%s vnet=%d\n", vif, vnet); + exit: + dprintf("< err=%d\n", err); + return err; +} + +int eval(Sxpr exp){ + int err = 0; + Sxpr oconnect = intern("connect"); + Sxpr ovnet = intern("vnet"); + + if(sxpr_elementp(exp, ovnet)){ + err = eval_vnet(exp); + } else if(sxpr_elementp(exp, oconnect)){ + err = eval_connect(exp); + } else { + err = -EINVAL; + } + return err; +} + +/** Main program for testing. + * Parses input and prints it. + * + * @param argc number of arguments + * @param argv arguments + * @return error code + */ +int main(int argc, char *argv[]){ + Parser *pin; + int err = 0; + char buf[1024]; + int k; + Sxpr obj; + //Sxpr l, x; + int i = 0; + + pin = Parser_new(); + set_error_stream(pin, iostdout); + dprintf("> parse...\n"); + while(1){ + k = fread(buf, 1, 1, stdin); + err = Parser_input(pin, buf, k); + while(Parser_ready(pin)){ + obj = Parser_get_val(pin); + printf("obj %d\n", i++); + objprint(iostdout, obj, 0); printf("\n"); + } + if(k <= 0) break; + } +/* obj = Parser_get_all(pin); */ +/* for(l = obj ; CONSP(l); l = CDR(l)){ */ +/* x = CAR(l); */ +/* objprint(iostdout, x, 0); printf("\n"); */ +/* eval(x); */ +/* } */ + dprintf("> err=%d\n", err); + return 0; +} +#endif diff --git a/tools/xfrd/sxpr_parser.h b/tools/xfrd/sxpr_parser.h new file mode 100644 index 0000000000..64a417608c --- /dev/null +++ b/tools/xfrd/sxpr_parser.h @@ -0,0 +1,133 @@ +/* + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. This library is + * distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _XUTIL_SXPR_PARSER_H_ +#define _XUTIL_SXPR_PARSER_H_ + +#include "sxpr.h" +#include "iostream.h" + +/** @file + * Sxpr parsing definitions. + */ + +/** Size of a parser input buffer. + * Tokens read must fit into this size (including trailing null). + */ +#define PARSER_BUF_SIZE 1024 + +struct Parser; +typedef int ParserStateFn(struct Parser *, char c); + +typedef struct ParserState { + struct ParserState *parent; + Sxpr val; + int ival; + int count; + char delim; + ParserStateFn *fn; + char *name; +} ParserState; + +/** Structure representing an input source for the parser. + * Can read from any IOStream implementation. + */ +typedef struct Parser { + Sxpr val; + /** Error reporting stream (null for no reports). */ + IOStream *error_out; + int eof; + /** Error flag. Non-zero if there has been a read error. */ + int err; + /** Line number on input (from 1). */ + int line_no; + /** Column number of input (reset on new line). */ + int char_no; + /** Lookahead character. */ + char c; + /** Buffer for reading tokens. */ + char buf[PARSER_BUF_SIZE]; + /** Size of token buffer. */ + int buf_n; + int buf_i; + /** Line the last token started on. */ + int tok_begin_line; + /** Character number the last token started on. */ + int tok_begin_char; + /** Parsing flags. */ + int flags; + ParserState *state; + ParserState *start_state; +} Parser; + +/** Parser error codes. */ +typedef enum { + PARSE_ERR_NONE=0, + PARSE_ERR_UNSPECIFIED, + PARSE_ERR_NOMEM, + PARSE_ERR_UNEXPECTED_EOF, + PARSE_ERR_TOKEN_TOO_LONG, + PARSE_ERR_INVALID_SYNTAX, + PARSE_ERR_INVALID_ESCAPE, +} ParseErrorId; + + +/** Parser flags. */ +//enum { +//}; + +/** Raise some parser flags. + * + * @param in parser + * @param flags flags mask + */ +inline static void parser_flags_raise(Parser *in, int flags){ + in->flags |= flags; +} + +/** Lower some parser flags. + * + * @param in parser + * @param flags flags mask + */ +inline static void parser_flags_lower(Parser *in, int flags){ + in->flags &= ~flags; +} + +/** Clear all parser flags. + * + * @param in parser + */ +inline static void parser_flags_clear(Parser *in){ + in->flags = 0; +} + +extern void Parser_free(Parser *z); +extern Parser * Parser_new(void); +extern int Parser_input(Parser *p, char *buf, int buf_n); +extern int Parser_input_eof(Parser *p); +extern int Parser_input_char(Parser *p, char c); +extern void set_error_stream(Parser *z, IOStream *error_out); + +extern int parse_error_message(Parser *in, char *buf, int n); +extern int has_error(Parser *in); +extern int at_eof(Parser *in); + +int Parser_ready(Parser *p); +Sxpr Parser_get_val(Parser *p); +Sxpr Parser_get_all(Parser *p); + +#endif /* ! _XUTIL_SXPR_PARSER_H_ */ diff --git a/tools/xfrd/xen_domain.c b/tools/xfrd/xen_domain.c index 5c5f7c5bef..4c197e8396 100644 --- a/tools/xfrd/xen_domain.c +++ b/tools/xfrd/xen_domain.c @@ -38,7 +38,7 @@ int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int v if(d > buf_n) d = buf_n; err = marshal_bytes(io, buf, d); if(err) goto exit; - //dprintf("> k=%d n=%d\n", k, n); + dprintf("> k=%d n=%d\n", k, n); } exit: @@ -68,7 +68,7 @@ int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n if(d > buf_n) d = buf_n; err = unmarshal_bytes(io, buf, d); if(err) goto exit; - //dprintf("> k=%d n=%d\n", k, n); + dprintf("> k=%d n=%d\n", k, n); } exit: #else diff --git a/tools/xfrd/xfrd.c b/tools/xfrd/xfrd.c index 1836231075..5dac7be0ba 100644 --- a/tools/xfrd/xfrd.c +++ b/tools/xfrd/xfrd.c @@ -36,7 +36,7 @@ #include "sys_net.h" #include "sys_string.h" -#include "xdr.h" +//#include "xdr.h" #include "enum.h" #include "xfrd.h" @@ -362,10 +362,10 @@ int addrof(Sxpr exp, uint32_t *v){ err = stringof(exp, &h); if(err) goto exit; if(get_host_address(h, &a)){ - *v = a; - } else { err = -EINVAL; + goto exit; } + *v = a; exit: dprintf("< err=%d v=%x\n", err, *v); return err; @@ -383,11 +383,12 @@ int portof(Sxpr exp, uint16_t *v){ unsigned long p; err = stringof(exp, &s); if(err) goto exit; - if(get_service_port(s, &p)){ - *v = p; - } else { + err = convert_service_to_port(s, &p); + if(err){ err = -EINVAL; + goto exit; } + *v = p; } exit: dprintf("< err=%d v=%u\n", err, *v); @@ -414,20 +415,12 @@ time_t stats(time_t t0, uint64_t offset, uint64_t memory, float *percent, float */ int xfr_error(Conn *conn, int errcode){ int err = 0; + if(!conn->out) return -ENOTCONN; - err = pack_type(conn->out, T_CONS); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, oxfr_err); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, mkint(errcode)); - if(err) goto exit; - err = pack_bool(conn->out, 0); - exit: - return err; + if(errcode <0) errcode = -errcode; + err = IOStream_print(conn->out, "(%s %d)", + atom_name(oxfr_err), errcode); + return (err < 0 ? err : 0); } /** Read a response message - error or ok. @@ -441,7 +434,7 @@ int xfr_response(Conn *conn){ dprintf(">\n"); if(!conn->out) return -ENOTCONN; - err = unpack_sxpr(conn->in, &sxpr); + err = Conn_sxpr(conn, &sxpr); if(err) goto exit; if(sxpr_elementp(sxpr, oxfr_err)){ int errcode; @@ -468,7 +461,7 @@ int xfr_hello(Conn *conn){ Sxpr sxpr; if(!conn->in) return -ENOTCONN; dprintf(">\n"); - err = unpack_sxpr(conn->in, &sxpr); + err = Conn_sxpr(conn, &sxpr); if(err) goto exit; if(!sxpr_elementp(sxpr, oxfr_hello)){ dprintf("> sxpr_elementp test failed\n"); @@ -503,21 +496,12 @@ int xfr_hello(Conn *conn){ int xfr_send_hello(Conn *conn){ int err = 0; dprintf(">\n"); - err = pack_type(conn->out, T_CONS); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, oxfr_hello); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, mkint(XFR_PROTO_MAJOR)); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, mkint(XFR_PROTO_MINOR)); - if(err) goto exit; - err = pack_bool(conn->out, 0); + + err = IOStream_print(conn->out, "(%s %d %d)", + atom_name(oxfr_hello), + XFR_PROTO_MAJOR, + XFR_PROTO_MINOR); + if(err < 0) goto exit; IOStream_flush(conn->out); dprintf("> xfr_response...\n"); err = xfr_response(conn); @@ -528,55 +512,26 @@ int xfr_send_hello(Conn *conn){ int xfr_send_xfr(Conn *conn, uint32_t vmid){ int err; - err = pack_type(conn->out, T_CONS); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, oxfr_xfr); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, mkint(vmid)); - if(err) goto exit; - err = pack_bool(conn->out, 0); - if(err) goto exit; - exit: - return err; + + err = IOStream_print(conn->out, "(%s %d)", + atom_name(oxfr_xfr), vmid); + return (err < 0 ? err : 0); } int xfr_send_ok(Conn *conn, uint32_t vmid){ int err = 0; - err = pack_type(conn->out, T_CONS); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, oxfr_ok); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, mkint(vmid)); - if(err) goto exit; - err = pack_bool(conn->out, 0); - exit: - return err; + + err = IOStream_print(conn->out, "(%s %d)", + atom_name(oxfr_ok), vmid); + return (err < 0 ? err : 0); } int xfr_send_suspend(Conn *conn, uint32_t vmid){ int err = 0; - err = pack_type(conn->out, T_CONS); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, oxfr_suspend); - if(err) goto exit; - err = pack_bool(conn->out, 1); - if(err) goto exit; - err = pack_sxpr(conn->out, mkint(vmid)); - if(err) goto exit; - err = pack_bool(conn->out, 0); - exit: - return err; + err = IOStream_print(conn->out, "(%s %d)", + atom_name(oxfr_suspend), vmid); + return (err < 0 ? err : 0); } /** Get vm state. Send transfer message. @@ -594,11 +549,12 @@ int xfr_send_state(XfrState *state, Conn *xend, Conn *peer){ // Send xfr message and the domain state. err = xfr_send_xfr(peer, state->vmid); if(err) goto exit; - err = xen_domain_snd(xend, peer->out, state->vmid, state->vmconfig, state->vmconfig_n); + err = xen_domain_snd(xend, peer->out, + state->vmid, state->vmconfig, state->vmconfig_n); if(err) goto exit; IOStream_flush(peer->out); // Read the response from the peer. - err = unpack_sxpr(peer->in, &sxpr); + err = Conn_sxpr(peer, &sxpr); if(err) goto exit; if(sxpr_elementp(sxpr, oxfr_err)){ // Error. @@ -785,10 +741,14 @@ int xfrd_service(Args *args, int peersock, struct sockaddr_in peer_in){ dprintf(">\n"); err = Conn_init(conn, flags, peersock, peer_in); if(err) goto exit; + dprintf(">xfr_hello... \n"); err = xfr_hello(conn); if(err) goto exit; - err = unpack_sxpr(conn->in, &sxpr); + dprintf("> sxpr...\n"); + err = Conn_sxpr(conn, &sxpr); if(err) goto exit; + dprintf("> sxpr=\n"); + objprint(iostdout, sxpr, PRINT_TYPE); IOStream_print(iostdout, "\n"); if(sxpr_elementp(sxpr, oxfr_migrate)){ // Migrate message from xend. uint32_t addr; diff --git a/tools/xfrd/xfrdClient.py b/tools/xfrd/xfrdClient.py index b8a3554729..1f1fc22407 100755 --- a/tools/xfrd/xfrdClient.py +++ b/tools/xfrd/xfrdClient.py @@ -34,13 +34,11 @@ class TCPClient: self.sockin = self.sock.makefile("r") self.sockout = self.sock.makefile("w") - self.packer = SxpPacker(self.sockout) - self.unpacker = SxpUnpacker(self.sockin) #pass def request(self, req): print "request>", req - self.packer.pack(req) + sxp.show(req, out=self.sockout) self.sockout.flush() print "request<" @@ -52,10 +50,10 @@ class TCPClient: def read(self): while(1): - v = self.unpacker.unpack() + v = self.sockin.read() print 'read>', v - if v[0] == 'xfr.err' and v[1]: return - if v[0] == 'xfr.ok': return + #if v[0] == 'xfr.err' and v[1]: return + #if v[0] == 'xfr.ok': return XFR_PROTO_MAJOR = 1 XFR_PROTO_MINOR = 0 -- 2.30.2